package com.swak.wechat;

import java.io.ByteArrayInputStream;
import java.security.KeyStore;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.swak.http.HttpService;
import com.swak.utils.Maps;
import com.swak.utils.ssl.SslContexts;
import com.swak.wechat.payv3.PrepayRequest;

import io.netty.handler.ssl.SslContext;
import lombok.Getter;

/**
 * Wechat 服务
 *
 * @author: lifeng
 * @date: 2020/4/1 11:38
 */
public abstract class AbstractMchv3Service {

	protected static final Logger logger = LoggerFactory.getLogger(AbstractMchv3Service.class);

	@Getter
	protected static class Wrap {
		private final String md5;
		private final HttpService service;

		Wrap(String md5, HttpService service) {
			this.md5 = md5;
			this.service = service;
		}
	}

	/**
	 * Http 服务
	 *
	 * @return http 服务
	 */
	public abstract HttpService getHttpService();

	/**
	 * SSl 服务: MchId -> HttpService
	 */
	private Map<String, Wrap> sslHttpServices = Maps.newConcurrentMap();

	/**
	 * 获取 SSl 服务， 如果有多个wechat 的ssl 需要处理可以根据  管理多个
	 *
	 * @param app app
	 * @return http ssl 服务
	 */
	public HttpService getSslHttpService(MchConfig app) {
		Wrap wrap = sslHttpServices.get(app.getMchId());
		if (wrap == null || !app.getSslCertDataMD5().equals(wrap.getMd5())) {
			synchronized (sslHttpServices) {
				wrap = sslHttpServices.get(app.getMchId());
				if (wrap == null || !app.getSslCertDataMD5().equals(wrap.getMd5())) {
					this.sslHttpServices.remove(app.getMchId());
					wrap = this.sslHttpServices.computeIfAbsent(app.getMchId(), key -> {
						Wrap _wrap = new Wrap(app.getSslCertDataMD5(),
								this.getHttpService().sslConfig(this.getSslContext(app)));
						return _wrap;
					});
				}
			}
		}
		return wrap.getService();
	}

	private SslContext getSslContext(MchConfig app) {
		try (ByteArrayInputStream in = new ByteArrayInputStream(app.getSslCertData())) {
			KeyStore keystore = KeyStore.getInstance("PKCS12");
			char[] partnerId2charArray = app.getMchId().toCharArray();
			keystore.load(in, partnerId2charArray);
			return SslContexts.forClient().useKeyStore(keystore, partnerId2charArray).build();
		} catch (Exception e) {
			logger.error("Set SSL error: ", e);
		}
		return null;
	}

	// ==========================================================
	// 微信支付： 下单 -> 查询订单 -> 退款 -> 退款查询
	// ==========================================================

	public CompletableFuture<Map<String, Object>> unifiedorder(MchConfig app, PrepayRequest request) {
		// String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/" + request.getTradetype();
		// String reqBody = JsonMapper.toJson(request);
		return CompletableFuture.completedFuture(null);
	}

	public CompletableFuture<Map<String, Object>> queryOrder(MchConfig app) {
		return CompletableFuture.completedFuture(null);
	}

	public CompletableFuture<Map<String, Object>> refundOrder(MchConfig app) {
		return CompletableFuture.completedFuture(null);
	}

	public CompletableFuture<Map<String, Object>> refundQuery(MchConfig app) {
		return CompletableFuture.completedFuture(null);
	}

	// ==========================================================
	// 发起请求
	// ==========================================================

	/**
	 * 请求
	 *
	 * @param client 客户端
	 * @param url    地址
	 * @param data   数据
	 * @return 异步结果
	 */
	public CompletableFuture<String> request(HttpService client, MchConfig app, String url, String data) {
		return client.post().textResult().setUrl(url).setHeader("Content-Type", "text/xml")
				.setHeader("User-Agent", "wxpay sdk java v1.0 " + app.getMchId())
				.setRequestTimeout(app.getHttpConnectTimeoutMs()).setReadTimeout(app.getHttpReadTimeoutMs())
				.setBody(data).future();
	}
}
